#! /bin/sh
ME="[makedvd]:"
. tovid-init

# makedvd
# Part of the tovid suite
# =======================
# A bash script for creating a DVD VIDEO_TS/VOB structure and
# burning it to a recordable DVD.
#
# Project homepage: http://www.tovid.org
#
#
# Copyright (C) 2005 tovid.org <http://www.tovid.org>
# 
# This program is free software; you can redistribute it and/or 
# modify it under the terms of the GNU General Public License 
# as published by the Free Software Foundation; either 
# version 2 of the License, or (at your option) any later 
# version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
#
#           http://www.gnu.org/licenses/gpl.txt

SCRIPTNAME=`cat << EOF
--------------------------------
makedvd
A script to create a DVD-Video file structure and burn it to DVD
Part of the tovid suite, version $TOVID_VERSION
$BUILD_OPTIONS
$TOVID_HOME_PAGE
--------------------------------
EOF`

USAGE=`cat << EOF
Usage: makedvd [OPTIONS] FILE.xml
   or: makedvd [OPTIONS] DVD_DIR

With FILE.xml, containing dvdauthor XML as generated by 'makexml',
or DVD_DIR, a directory containing a DVD filesystem (VIDEO_TS, namely).

OPTIONS may be any of the following:

  -author              Create DVD filesystem from FILE.xml
  -burn                Burn DVD filesystem from DVD_DIR
  -device DEVFS_NAME   DVD recorder device name (Default: /dev/dvdrw)
  -speed NUM           Burn speed (Default: automatic)
  -label DISC_LABEL    Disc label (Default: base name of FILE)

See the makedvd manual page ('man makedvd') for additional documentation.
EOF`

# Print script name, usage notes, and optional error message, then exit.
# Args: $1 == text string containing error message
usage_error ()
{
  echo "$USAGE"
  echo $SEPARATOR
  echo "$@"
  exit 1
}

# Print out a runtime error specified as an argument, and exit
runtime_error ()
{
    #killsubprocs
    echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    echo "makedvd encountered an error during the DVD creation process:"
    echo "$@"
    echo "See if anything in the above output helps you diagnose the"
    echo "problem, and please file a bug report at tovid.org (_not_"
    echo "the dvdauthor list) containing the above output."
    echo "Sorry for the inconvenience!"
    echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    exit 1
}

# Defaults
# Create the DVD filesystem hierarchy?
DO_AUTHOR=false
# Burn the image to disc?
DO_BURN=false

# Guess for the device
DVD_SIZE_MB=4300
DVDRW_DEVICE="/dev/dvdrw"
BURN_SPEED=""
OUT_DIR="makedvd_out"
DISC_LABEL=""

# Grab DVD media information
# Returns nothing, but sets the 'global' variables 
#   MEDIA_INFO, DISC_STATUS, and DISC_TYPE
probe_media ()
{
  # Grab entire media info
  MEDIA_INFO=$(dvd+rw-mediainfo $DVDRW_DEVICE 2>&1)

  # Extract the status (either "blank" or "complete")
  DISC_STATUS=$(echo "$MEDIA_INFO" | grep "Disc status" | awk '{ print $3 }')

  # Extract the disc type
  DISC_TYPE=$(echo "$MEDIA_INFO" | grep "Mounted Media" | awk '{ print $4 }')
  if test -z $DISC_TYPE; then 
     if echo "$MEDIA_INFO" | grep -q "non-DVD"; then
        DISC_TYPE="non-DVD media"
     else
        DISC_TYPE="no disc"
     fi
  fi

  # Find the capcity
  DISC_CAPACITY=$(echo "$MEDIA_INFO" | grep "Legacy lead-out" | \
                  awk -F '=' '{print $2}')
  if test -z $DISC_CAPACITY; then DISC_CAPACITY=0; fi
  DISC_CAPACITY=$(echo "$DISC_CAPACITY / 1024 / 1024" | bc)

  # Define usable DVDs
  HAVE_DVD_RW=$(verify "$DISC_TYPE" set "DVD-RW DVD+RW")
  if $(verify "$DISC_TYPE" set "DVD-R DVD+R") && test "x$DISC_STATUS" = "xblank"
    then HAVE_BLANK_DVD_R=:
    else HAVE_BLANK_DVD_R="false"
  fi
}


# ==========================================================
# EXECUTION BEGINS HERE
echo $"$SCRIPTNAME"

assert_dep_group "dvd" "You are missing dependencies required for burning DVDs!"

if test $# -lt 1; then
    usage_error "Please provide a filename (.xml, or dvd filesystem folder)"
fi

while test $# -gt 1; do
    case "$1" in
        "-author" ) DO_AUTHOR=: ;;
        "-burn" )   DO_BURN=: ;;
        "-device" )
            # Get device name
            shift
            DVDRW_DEVICE="$1"
            ;;
        "-speed" )
            shift
            BURN_SPEED="-speed=$1"
            ;;
        "-label" )
            shift
            DISC_LABEL="$1"
            ;;
        * )
            usage_error "Error: Unrecognized command-line option '$1'"
            ;;
    esac

    # Get next argument
    shift
done

DISC_NAME=$(abspath "$1")

# See what kind of file we're working with, and do the right thing
# Author an XML file
if echo "$DISC_NAME" | grep -q -i '\.xml$'; then
    DVDAUTHOR_XML="$DISC_NAME"
    DO_AUTHOR=:
    # Make sure the XML file exists
    if test ! -f "$DVDAUTHOR_XML"; then
        echo "Could not open file: $DVDAUTHOR_XML"
        exit 1
    else
        echo "Authoring disc from file: $DVDAUTHOR_XML"
    fi
    # The dest= argument from the XML file will be the output directory
    OUT_DIR=$(grep 'dest=' "$DVDAUTHOR_XML" | awk -F '"' '{print $2}')
    echo "Putting output in directory: ./$OUT_DIR/"
# Burn a directory containing a VIDEO_TS subfolder
elif test -d "$DISC_NAME"; then
    if test -d "$DISC_NAME/VIDEO_TS"; then
        DO_BURN=:
        OUT_DIR="$DISC_NAME"
    fi
fi

# Set disc title and output directory based on given filename
# (without .xml, space to underscore)
test -z $DISC_LABEL && DISC_LABEL=$( basename "$DISC_NAME" ".xml" | tr ' ' '_')
# And, just in case that failed...
test -z $DISC_LABEL && DISC_LABEL="UNTITLED_DVD"

# Authoring
if $DO_AUTHOR; then
    # Determine how much space will be needed for authoring, by adding up
    # the sizes of all .vobs in the XML file.
    NUM_VOBS=$(grep vob "$DVDAUTHOR_XML" | wc -l)
    VOB_LIST=$(grep vob "$DVDAUTHOR_XML" | \
               awk -F '"' '{ print $2 }' | tr '\n' ':')
    i=1
    DISC_SUM=0
    while test $i -le $NUM_VOBS; do
      VOB=$(echo "$VOB_LIST" | awk -F ':' '{ print $'$i' }')
      VOB_SIZE=$(du -B M "$VOB" | awk -F ' ' '{print $1}' | tr -d M)
      DISC_SUM=$(expr $VOB_SIZE \+ $DISC_SUM)
      i=$(expr $i \+ 1)
    done
    AVAIL_SPACE=$(df -B M -P . | awk 'NR != 1 {print $4;}' | tr -d M)

    if test $DISC_SUM -gt $AVAIL_SPACE; then
       echo $SEPARATOR
       precho "Cannot continue! ${DISC_SUM}MB needed, but only ${AVAIL_SPACE}MB in $(pwd)"
       echo "Exiting..."
       exit 1
    fi
    if test $DISC_SUM -gt $DVD_SIZE_MB; then
       echo $SEPARATOR
       echo "Warning! Making a DVD image larger than a standard single-sided DVD."
       echo "Current DVD image is ${DISC_SUM}MB."
    fi

    # Create disc structure
    DVDAUTHOR_CMD="dvdauthor -x \"$DVDAUTHOR_XML\""
    echo $SEPARATOR
    echo "Authoring DVD-Video disc structure, estimated to require ${DISC_SUM}MB."
    echo "Creating disc structure with the following command:"
    echo $DVDAUTHOR_CMD
    echo $SEPARATOR
    
    if eval "$DVDAUTHOR_CMD" 2>&1; then
        echo $SEPARATOR
        echo "Disc structure successfully created in directory: $OUT_DIR."
    else
        runtime_error "Could not create the DVD-Video disc structure in $OUT_DIR. Leaving $OUT_DIR for inspection."
    fi

echo "Authoring completed."
fi

# If not burning, print a message and exit
if ! $DO_BURN; then
    echo "You can burn the disc with a command like this:"
    echo "  $ makedvd -burn $OUT_DIR"

# Otherwise, get on with burning
else
    # Remind user to insert a DVD, check for DVD device
    echo $SEPARATOR
    echo "Please insert a blank DVD+/-R(W) disc into your DVD-recorder"
    echo "($DVDRW_DEVICE) if you have not already done so."

    # Sanity check: Make sure given device is valid (somehow)
    # before creating the image. Give option to proceed anyway?
    # (i.e., could there be any point to proceeding?)
    # Here's a simple way: just quit
    if test -b $DVDRW_DEVICE; then :
    else
      precho "Couldn't find $DVDRW_DEVICE! Are you sure your burner is $DVDRW_DEVICE? Specify your burner with '-device /path/to/burner'."
      echo "Stopping here."
      exit 1
    fi

    GROWISOFS_VER=$(growisofs -version | grep version | \
                    awk '{ print $6 }' | sed 's/,//g')

    # Make sure there is a blank disc to write to
    probe_media

    if ! $HAVE_DVD_RW && ! $HAVE_BLANK_DVD_R; then
      echo $SEPARATOR
      echo "Found $DISC_TYPE in $DVDRW_DEVICE. Cannot burn to this disc!"
      until $HAVE_DVD_RW || $HAVE_BLANK_DVD_R
      do
        TIME_SCALE=1
        # TODO: smarter loop. User feedback (ie "hit any key" [where's the "any"
        # key anyway?]) is bad for when makedvd is called from the gui. But, it
        # usually takes 2 cycles for the dvd player to recognize a new disc. Is
        # there a better interface to it? Waiting till the drive's LED goes off
        # is good, but how?
        echo "Found $DISC_STATUS $DISC_TYPE. Please insert a usable DVD into $DVDRW_DEVICE."
        for COUNTER in 5 4 3 2 1; do
          printf "Trying again in %2s seconds...\r" $(expr $COUNTER \* $TIME_SCALE)
          sleep ${TIME_SCALE}s
        done
        echo
        echo "Looking for usable media..."
        probe_media
      done
    fi

    echo $SEPARATOR
    echo "Found $DISC_STATUS $DISC_TYPE."

    DISC_SUM=$(du -s -B M "$OUT_DIR" | awk '{print $1}' | tr -d M)
    if test $DISC_SUM -gt $DISC_CAPACITY; then
       echo $SEPARATOR
       echo "Cannot continue! DVD image (${DISC_SUM}MB) exceeds the DVD's capacity (${DISC_CAPACITY}MB)."
       echo "Exiting..."
       exit 1
    fi

    # complete DVD+/-RW need explicit blanking
    # a bug report for tkDVD points out that -use-the-force-luke=tty is req'd to
    # burn to complete +/-RW discs:
    # http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=10751
    # but this support is still spotty (works for grepper and his +RW, but not 
    # friedrij and his -RW)
    if test "x$DISC_STATUS" = "xcomplete"; then 
      echo $SEPARATOR
      echo "Found $DISC_STATUS $DISC_TYPE in $DVDRW_DEVICE. Blanking..."
      dvd+rw-format -blank $DVDRW_DEVICE
    fi
    
    # Extract a valid volume ID
    VOLID=$(echo "$DISC_LABEL" | tr a-z A-Z)
    # Make sure we have a valid VOLID at this point...can't be too long
    VALID_VOLID=$(echo $VOLID | awk '{ print substr($0, 0, 32) }')
    if test $VOLID != $VALID_VOLID; then
        echo "Disk label is too long. Truncating to $VALID_VOLID"
        VOLID=$VALID_VOLID
    else
        echo "Using disk label \"$VOLID\""
    fi
 
    # Burn it already!
    BURN_CMD="growisofs -use-the-force-luke=dao -dvd-compat $BURN_SPEED -Z $DVDRW_DEVICE -dvd-video -V \"$VOLID\" \"$OUT_DIR\""
    echo $SEPARATOR
    echo "Burning with growisofs $GROWISOFS_VER using the following command:"
    echo "$BURN_CMD"
    echo $SEPARATOR
    if eval "$BURN_CMD" 2>&1; then
        echo $SEPARATOR
        echo "Done. You should now have a working DVD. Please visit"
        echo "the tovid homepage: $TOVID_HOME_PAGE"
    else
        runtime_error "Could not burn the disc to $DVDRW_DEVICE"
    fi
fi
    
echo $SEPARATOR
echo "Thanks for using makedvd!"

exit 0
